package com.css.fxfzfxqh.util;

import org.junit.Test;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
@Service
public class FImCountUtils {
    @Resource
    private ThreadPoolUtil threadPoolUtil;
//    public Map<String,List<Object>> fImCount(BigDecimal sdmr,BigDecimal mdmr,BigDecimal edmr,BigDecimal collapseMr,BigDecimal sdBr,BigDecimal mdBr,BigDecimal edBr,BigDecimal collapseBr) {
//        Map<String,List<Object>> returnMap=new HashMap<>();
//        List<Object> listy = new LinkedList<>();
//        try {
//            BigDecimal startImValue = new BigDecimal(0.05);
//            BigDecimal endImValue = new BigDecimal(2.00);
//            BigDecimal intervalValue = new BigDecimal(0.05);
//
//            Map<String, Map<BigDecimal, BigDecimal>> mapMap = new HashMap<>();
//
//            while (startImValue.compareTo(endImValue.add(intervalValue)) < 1) {
//                if (startImValue.compareTo(endImValue) > 0) {
//                    startImValue = endImValue;
//                }
//                BigDecimal a2 = BigDecimal.valueOf(startImValue.doubleValue());
//                //起线程
//                int threadNum = 4;
//                ExecutorService executorService = threadPoolUtil.getFixedThreadPool(threadNum);
//                List<Future> futureList = new ArrayList<>();
//                for (int j = 0; j < threadNum; j++) {
//                    BigDecimal temp = new BigDecimal(0);
//                    try {
//                        if (j == 0) {
//                            temp = a2.subtract(BigDecimal.valueOf(Math.log(sdmr.doubleValue()))).divide(sdBr, 2,
//                                    BigDecimal.ROUND_HALF_UP);
//                        } else if (j == 1) {
//                            temp = a2.subtract(BigDecimal.valueOf(Math.log(mdmr.doubleValue()))).divide(mdBr, 2,
//                                    BigDecimal.ROUND_HALF_UP);
//                        } else if (j == 2) {
//                            temp = a2.subtract(BigDecimal.valueOf(Math.log(edmr.doubleValue()))).divide(edBr, 2,
//                                    BigDecimal.ROUND_HALF_UP);
//                        } else if (j == 3) {
//                            temp = a2.subtract(BigDecimal.valueOf(Math.log(collapseMr.doubleValue())).divide(collapseBr, 2,
//                                    BigDecimal.ROUND_HALF_UP));
//                        }
//                    } catch (ArithmeticException e) {
//                        temp = BigDecimal.ZERO;
//                    }
//                    Callable callable = new ReloadCallable(temp, "signal");
//                    Future submit = executorService.submit(callable);
//                    futureList.add(submit);
//                }
//                executorService.shutdown();
//
//                BigDecimal FIM1 = (BigDecimal) futureList.get(0).get();
//                BigDecimal FIM2 = (BigDecimal) futureList.get(1).get();
//                BigDecimal FIM3 = (BigDecimal) futureList.get(2).get();
//                BigDecimal FIM4 = (BigDecimal) futureList.get(3).get();
//
//                Map<BigDecimal, BigDecimal> map = null;
//                if (mapMap.containsKey("SD")) {
//                    map = mapMap.get("SD");
//                } else {
//                    map = new TreeMap<>();
//                }
//                map.put(startImValue, FIM1);
//                mapMap.put("SD", map);
//                if (mapMap.containsKey("MD")) {
//                    map = mapMap.get("MD");
//                } else {
//                    map = new TreeMap<>();
//                }
//                map.put(startImValue, FIM2);
//                mapMap.put("MD", map);
//                if (mapMap.containsKey("ED")) {
//                    map = mapMap.get("ED");
//                } else {
//                    map = new TreeMap<>();
//                }
//                map.put(startImValue, FIM3);
//                mapMap.put("ED", map);
//                if (mapMap.containsKey("CD")) {
//                    map = mapMap.get("CD");
//                } else {
//                    map = new TreeMap<>();
//                }
//                map.put(startImValue, FIM4);
//                mapMap.put("CD", map);
//
//                if (startImValue.compareTo(endImValue) == 0) {
//                    break;
//                }
//                startImValue = startImValue.add(intervalValue);
//            }
//
//            List<Object> xx = new LinkedList<>();
//            for (String key : mapMap.keySet()) {
//                listy = new LinkedList<>();
//                Map<BigDecimal, BigDecimal> map = mapMap.get(key);
//                for (Map.Entry<BigDecimal, BigDecimal> entry : map.entrySet()) {
//                    // 将 x 和 y 值列表添加到结果映射中
//                    listy.add(entry.getValue().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
//                    if("SD".equals(key)){//只循环一次取 X轴枚举
//                        xx.add(entry.getKey().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
//                    }
//                }
//                returnMap.put(key, listy);
//            }
//            returnMap.put("xx",xx);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return returnMap;
//    }
    public Map<String,List<Object>> fImCount(BigDecimal sdVal,BigDecimal mdVal,BigDecimal edVal,BigDecimal collapseVal) {
        Map<String,List<Object>> returnMap=new HashMap<>();
        List<Object> listy = new LinkedList<>();
        try {
            BigDecimal startImValue = new BigDecimal(0.05);
            BigDecimal endImValue = new BigDecimal(2.00);
            BigDecimal intervalValue = new BigDecimal(0.05);

            Map<String, Map<BigDecimal, BigDecimal>> mapMap = new HashMap<>();

            while (startImValue.compareTo(endImValue.add(intervalValue)) < 1) {
                if (startImValue.compareTo(endImValue) > 0) {
                    startImValue = endImValue;
                }
                BigDecimal a2 = BigDecimal.valueOf(startImValue.doubleValue());
                //起线程
                int threadNum = 4;
                ExecutorService executorService = threadPoolUtil.getFixedThreadPool(threadNum);
                List<Future> futureList = new ArrayList<>();
                for (int j = 0; j < threadNum; j++) {
                    BigDecimal temp = new BigDecimal(0);
                    try {
                        if (j == 0) {
                            temp = sdVal;
                        } else if (j == 1) {
                            temp = mdVal;
                        } else if (j == 2) {
                            temp = edVal;
                        } else if (j == 3) {
                            temp =collapseVal;
                        }
                    } catch (ArithmeticException e) {
                        temp = BigDecimal.ZERO;
                    }
                    Callable callable = new ReloadCallable(temp, "signal");
                    Future submit = executorService.submit(callable);
                    futureList.add(submit);
                }
                executorService.shutdown();

                BigDecimal FIM1 = (BigDecimal) futureList.get(0).get();
                BigDecimal FIM2 = (BigDecimal) futureList.get(1).get();
                BigDecimal FIM3 = (BigDecimal) futureList.get(2).get();
                BigDecimal FIM4 = (BigDecimal) futureList.get(3).get();

                Map<BigDecimal, BigDecimal> map = null;
                if (mapMap.containsKey("SD")) {
                    map = mapMap.get("SD");
                } else {
                    map = new TreeMap<>();
                }
                map.put(startImValue, FIM1);
                mapMap.put("SD", map);
                if (mapMap.containsKey("MD")) {
                    map = mapMap.get("MD");
                } else {
                    map = new TreeMap<>();
                }
                map.put(startImValue, FIM2);
                mapMap.put("MD", map);
                if (mapMap.containsKey("ED")) {
                    map = mapMap.get("ED");
                } else {
                    map = new TreeMap<>();
                }
                map.put(startImValue, FIM3);
                mapMap.put("ED", map);
                if (mapMap.containsKey("CD")) {
                    map = mapMap.get("CD");
                } else {
                    map = new TreeMap<>();
                }
                map.put(startImValue, FIM4);
                mapMap.put("CD", map);

                if (startImValue.compareTo(endImValue) == 0) {
                    break;
                }
                startImValue = startImValue.add(intervalValue);
            }

            List<Object> xx = new LinkedList<>();
            for (String key : mapMap.keySet()) {
                listy = new LinkedList<>();
                Map<BigDecimal, BigDecimal> map = mapMap.get(key);
                for (Map.Entry<BigDecimal, BigDecimal> entry : map.entrySet()) {
                    // 将 x 和 y 值列表添加到结果映射中
                    listy.add(entry.getValue().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    if("SD".equals(key)){//只循环一次取 X轴枚举
                        xx.add(entry.getKey().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
                    }
                }
                returnMap.put(key, listy);
            }
            returnMap.put("xx",xx);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnMap;
    }


    /**
     * 计算fai
     *
     * @param u
     */
    public static BigDecimal selfCaculate(BigDecimal u) {
        BigDecimal ret = BigDecimal.valueOf(0);
        if (u.compareTo(BigDecimal.valueOf(-3.89)) < 0) {
            return new BigDecimal(0);
        } else if (u.compareTo(BigDecimal.valueOf(3.89)) > 0) {
            return new BigDecimal(1);
        }
        BigDecimal temp = BigDecimal.valueOf(-3.89);
        while (temp.compareTo(u) < 1) {
            ret = ret.add(BigDecimal.valueOf(0.0001).multiply(fx(temp)));
            temp = temp.add(BigDecimal.valueOf(0.0001));
        }
        return ret;
    }

    private static BigDecimal fx(BigDecimal x) {
        double a = 1.0 / Math.sqrt(Math.PI * 2);
        a = a * Math.pow(Math.E, -0.5 * Math.pow(Double.parseDouble(x.toString()), 2));
        return BigDecimal.valueOf(a);
    }

    class ReloadCallable implements Callable<Object> {
        private BigDecimal value;
        private BigDecimal temp;
        private String type;

        ReloadCallable(BigDecimal value, String type) {
            this.value = value;
            this.type = type;
        }

        ReloadCallable(BigDecimal value, BigDecimal temp, String type) {
            this.type = type;
            this.value = value;
            this.temp = temp;
        }

        @Override
        public Object call() throws Exception {
            if ("signal".equals(type)) {
                return selfCaculate(value);
            } else if ("for".equals(type)) {
                return temp(value, temp);
            } else if ("temp".equals(type)) {
                return fx(value);
            }
            return null;
        }
    }

    private static List<BigDecimal> temp(BigDecimal ret, BigDecimal temp) {
        List<BigDecimal> bList = new ArrayList<>();
        ret = ret.add(BigDecimal.valueOf(0.0001).multiply(fx(temp)));
        temp = temp.add(BigDecimal.valueOf(0.0001));
        bList.add(0, ret);
        bList.add(1, temp);
        return bList;
    }
//    @Test
//    public  void test() {
//        BigDecimal startImValue1 = new BigDecimal(0.02);
//        BigDecimal startImValue2 = new BigDecimal(0.01);
//        BigDecimal startImValue3 = new BigDecimal(0.02);
//        BigDecimal startImValue4 = new BigDecimal(0.01);
//        BigDecimal startImValue5 = new BigDecimal(0.02);
//        BigDecimal startImValue6 = new BigDecimal(0.01);
//        BigDecimal startImValue7 = new BigDecimal(0.02);
//        BigDecimal startImValue8 = new BigDecimal(0.01);
//        Map<String, List<Object>> stringListMap = this.fImCount(null,null,null,null,startImValue5,startImValue6,startImValue7,startImValue8);
//        System.out.println(stringListMap);
//    }
}
